#coding=utf-8
import time

__author__ = 'Meteor'

'''
构建一个基础操作类，类中提供页面操作方法
1、selenium封装
	1、特点：
		将所有的页面上的功能，封装成一个个函数。在用例中调用函数，来实现用例的执行
		这种模式就是典型的关键字驱动，但是对selenium页面操作，并未做封装，那么就会产生测试人员需要熟练掌握selenium的各种操作
		以及解决各种可能出现的错误。
		脚本开发人员，需要对每一步操作，都要考虑稳定性的问题
		
	2、对selenium的封装
		1、简化对selenium操作
		2、在封装层解决元素定位稳定问题
		
		操作问题：
		1、分析整个页面，需要对页面元素做哪些操作，封装selenium，对外提供具体的操作方法
		2、创建Base类，在类中封装页面操作方法：
			__init__：打开浏览器
			get：跳转URL地址
			find_element：元素定位方法，加入了显示等待
			find_elements：定位一组元素，以列表形式返回
			send_keys：输入框中，输入内容
				Base_object.send_keys(element,key)
				element = (By.ID,"id value")
				key：字符串
			click：点击元素
				Base_object.click(element)
				element = (By.ID,"id value")
			clear：清空内容
				Base_object.clear(element)
				element = (By.ID,"id value")
			get_text：返回元素中的文本
				Base_object.get_text(element)
				element = (By.ID,"id value")
			get_title：返回页面的title
				Base_object.get_title()
			select：下拉框选择
				Base_object.select(element,text)
				element = (By.ID,"id value")：必须是select标签元素
				text：下拉选项的文本内容
			
			select_div：div类型的下拉选项
				Base_object.select(element,text)
				element = (By.ID,"id value")
				text：下拉选项的文本内容
				
			move_to_element：移动鼠标到指定元素
				Base_object.select(element,text)
				element = (By.ID,"id value")
			
			close：关闭窗口
			quit：关闭所有窗口

'''
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.action_chains import ActionChains

from selenium.common.exceptions import NoSuchElementException,InvalidArgumentException,TimeoutException,\
    UnexpectedTagNameException,NoSuchFrameException,JavascriptException

from tools.log import  logger
import os,seting

class Base:
    # 打开浏览器
    def __init__(self,driver):
        '''
        如果在父类的构造方法中，实现打开浏览器，那么子类创建对象时，都会调用构造方法，那么将会打开多个页面
        所以构造方法中，不能直接打开浏览器，修改为一个浏览器对象向
        '''
        self.driver = driver
        logger.info('打开chrome浏览器')
        # self.driver.maximize_window()

        #调用get方法，操作浏览器跳转到指定的URL地址
        self.get(seting.URL)

    # 浏览器跳转
    def get(self,url):
        try:
            self.driver.get(url)
            logger.info('跳转到地址：%s' %url)
        except InvalidArgumentException as IAE:
            logger.error('%s URL error:%s ' %(IAE,url))
            raise InvalidArgumentException

    # 元素定位
    def find_element(self,elemnt):
        if elemnt[0] not in [By.ID,By.CLASS_NAME,By.CSS_SELECTOR,By.XPATH,By.LINK_TEXT,By.NAME,By.PARTIAL_LINK_TEXT,By.TAG_NAME]:
            logger.error('find element error %s' %str(elemnt))
            return


        try:
            WebDriverWait(self.driver, seting.WAIT_TIMEOUT).until(ec.visibility_of_element_located((elemnt)))
            logger.info('find element %s' %elemnt[1])
            return self.driver.find_element(elemnt[0],elemnt[1])
        except TimeoutException as ts:
            # 如果定位元素超时，记录error日志
            logger.error('element find error %s' %str(elemnt))
            raise TimeoutException

    def find_elements(self,element):
        try:
            WebDriverWait(self.driver, seting.WAIT_TIMEOUT).until(ec.visibility_of_element_located((element)))
            logger.info('find element %s' % element[1])
            return self.driver.find_elements(element[0],element[1])
        except TimeoutException:
            logger.error('element find error %s' % str(element))
            raise TimeoutException

    # 元素定位
    def findelement(self,element):
        # element= "id=loginName"
        by = element.split("=",maxsplit=1)[0]
        ele = element.split("=",maxsplit=1)[1]
        if by == 'id':
            WebDriverWait(self.driver, 10).until(ec.visibility_of_element_located((By.ID,ele)))
            return self.driver.find_element_by_id(ele)

        elif by == "name":
            WebDriverWait(self.driver, 10).until(ec.visibility_of_element_located((By.Name, ele)))
            return self.driver.find_element_by_name(ele)



    # 输入框输入数据
    def send_keys(self,element,key):
        #elemetn = (By.ID,"loginName")
        # element = "id=loginName"
        self.find_element(element).send_keys(key)
        logger.info('exec inout element:%s , key word:%s' %(str(element),key))

    # 元素点击
    def click(self,element):
        try:
            self.find_element(element).click()
            logger.info('click element %s' %str(element))
        except AttributeError:
            logger.error('click element error : %s' %str(element))
            raise AttributeError


    #清空元素中的数据
    def clear(self,element):
        self.find_element(element).clear()
        logger.info('clear element :%s' %str(element))

    #获取元素上的文本
    def get_text(self,element):
        logger.info('get element text: %s' %str(element))
        return self.find_element(element).text

    # 获取title
    def get_title(self):
        return self.driver.title

    def select(self,element,text):
        '''
        下拉框选择方法，必须传入select标签实现的下拉框的元素
        :param element: SELECT tag
        :param text: 下拉选项的文本内容
        :return: 
        '''
        try:
            Select(self.find_element(element)).select_by_visible_text(text)
            logger.info('select option :%s, option:%s' %(str(element),text))
        except UnexpectedTagNameException as ute:
            logger.error('select option Exception :%s' %ute)
            raise UnexpectedTagNameException

    def select_div(self,element,text):
        options  = self.find_elements(element)
        for option in options:
            if option.text == text:
                option.click()
                logger.info('select option %s' %text)
                break


    def move_to_element(self,element):
        '''
        将鼠标移动到指定元素
        :param element: 目标元素
        :return: 
        '''
        logger.info('mouse move to elemt:%s' %str(element))
        ActionChains(self.driver).move_to_element(self.find_element(element)).perform()

    def close(self):
        self.driver.close()

    def quit(self):
        self.driver.quit()

    def switch_to_frame(self,value):
        time.sleep(5)
        try:

            self.driver.switch_to.frame(value)
            logger.info('frame switch to: %s' %value)

        except NoSuchFrameException as NSFE:
            logger.error('frame not fond: %s :%s' %(value,NSFE))
            raise NoSuchFrameException

    def switch_to_default_frame(self):
        self.driver.switch_to.default_content()
        logger.info('switch to default frame')

    def switch_to_window(self,index):
        handles = self.driver.window_handles
        if index >= len(handles):
            logger.error('window not fond %s' %str(index))
            return
        for i in handles:
            self.driver.switch_to.window(handles[index])
            logger.info('switch to window sescc')

    def open_in_current_window(self,element):
        '''
        该方法用于实现点击链接时，新的链接在当前窗口打开
        :param element: 
        :return: 
        '''
        # element = (By.ID,"")
        js = ''
        if element[0] == 'id':
            js = '''document.getElementById("%s").target='_self';'''  %element[1]

        elif element[0] =="class name":
            js = """document.getElementsByClassName("%s")[0].target='_self';""" %element[1]
        elif element[0] == "name":
            js = """document.getElementsByName("%s")[0].target='_self'""" %element[1]

        if js:

            self.exec_js(js)

            self.click(element)


    def exec_js(self,js):
        try:
            self.driver.execute_script(js)
            logger.info("beging exec js: %s" % js)
        except JavascriptException as jse:
            logger.error('%s,%s' %(jse,js))
            raise JavascriptException


    def is_exist_element(self,element):
        try:
            if self.find_element(element).is_displayed():

                return True
            else:
                return False
        except:
            return False

    def uploadfile(self,file):
        if os.path.isfile(file):
            cmd = os.path.join(seting.BASEPATH, 'tools', 'uploadFile.exe %s' % file)
            os.system(r'%s' %cmd)
            logger.info('exec cmmond: %s' %cmd)
        else:
            logger.error('file is not exist: %s' %file)

    def screenshot_as_file(self,fileName):
        # 截图（当用例执行失败时，可以截图）
        self.driver.get_screenshot_as_file(fileName)

    def get_page_source(self):
        return self.driver.page_source

    def get_courent_url(self):
        return self.driver.current_url






if __name__ == "__main__":
    b = Base()
    b.get('https://www.baidu.com')

